/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */
package com.yami.shop.multishop.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.bean.app.dto.ProductDto;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.*;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.OfflineHandleEventAuditParam;
import com.yami.shop.bean.param.ProductParam;
import com.yami.shop.bean.vo.ComboProdSkuVO;
import com.yami.shop.bean.vo.ComboProdVO;
import com.yami.shop.combo.multishop.service.ComboProdService;
import com.yami.shop.combo.multishop.service.GiveawayProdService;
import com.yami.shop.common.bean.SysProdConfig;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.StatusEnum;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.delivery.common.model.SameCity;
import com.yami.shop.delivery.common.model.Transport;
import com.yami.shop.delivery.common.service.SameCityService;
import com.yami.shop.delivery.common.service.TransportService;
import com.yami.shop.security.multishop.model.YamiShopUser;
import com.yami.shop.security.multishop.util.SecurityUtils;
import com.yami.shop.service.*;
import com.yami.shop.sys.common.service.ShopEmployeeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 商品列表、商品发布controller
 *
 * @author lgh
 */
@RestController
@RequestMapping("/prod/prod")
@Api(tags = "商品接口")
public class ProductController {

    @Autowired
    private ProductService productService;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private SkuService skuService;
    @Autowired
    private BasketService basketService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private OfflineHandleEventService offlineHandleEventService;
    @Autowired
    private ShopDetailService shopDetailService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private ProductExcelService productExcelService;
    @Autowired
    private CategoryShopService categoryShopService;
    @Autowired
    private BrandShopService brandShopService;
    @Autowired
    private CategoryBrandService categoryBrandService;
    @Autowired
    private Snowflake snowflake;
    @Autowired
    private SupplierProdService supplierProdService;
    @Autowired
    private SameCityService sameCityService;
    @Autowired
    private ShopEmployeeService shopEmployeeService;
    @Autowired
    private ProdParameterService prodParameterService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private ComboProdService comboProdService;
    @Autowired
    private GiveawayProdService giveawayProdService;
    @Autowired
    private TransportService transportService;
    @Autowired
    private ProdExtensionService prodExtensionService;

    /**
     * 处理下活动商品的价格
     *
     * @param product  筛选参数
     * @param products 商品列表
     */
    private void processActivityProdPrice(ProductParam product, List<Product> products) {
        Map<Integer, List<Product>> prodMap = products.stream().collect(Collectors.groupingBy(Product::getProdType));
        if (prodMap.containsKey(ProdType.PROD_TYPE_SECKILL.value())) {
            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_SECKILL.value())));
        }

        if (prodMap.containsKey(ProdType.PROD_TYPE_GROUP.value())) {
            applicationContext.publishEvent(new ProcessActivityProdPriceEvent(product, prodMap.get(ProdType.PROD_TYPE_GROUP.value())));
        }
    }

    @GetMapping("/listProdByIdsAndType")
    @ApiOperation(value = "批量获取商品信息", notes = "批量获取商品信息")
    public ServerResponseEntity<List<ProductDto>> listProdByIdsAndType(ProductParam product) {
        product.setLang(I18nMessage.getDbLang());
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        List<Product> products = productService.listProdByIdsAndType(product);
        List<ProductDto> productDtos = mapperFacade.mapAsList(products, ProductDto.class);
        processActivityProdPrice(product, products);
        return ServerResponseEntity.success(productDtos);
    }

    @GetMapping("/pageOnLineProd")
    @ApiOperation(value = "分页获取上架的商品信息", notes = "分页获取上架的商品信息")
    public ServerResponseEntity<IPage<Product>> pageOnLineProd(ProductParam product, PageParam<Product> page) {
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Product> products = productService.pageProducts(page, product);
        return ServerResponseEntity.success(products);
    }

    @GetMapping("/info/{prodId}")
    @ApiOperation(value = "根据商品id获取商品信息", notes = "根据商品id获取商品信息")
    public ServerResponseEntity<Product> info(@PathVariable("prodId") Long prodId) {
        Product prod = productService.getProductById(prodId);
        if (!Objects.isNull(prod)){
            //先判断是否为空
            if (prod.getStatus() == -1){
                //商品状态不正确，请退出重试
                throw new YamiShopBindException("yami.prod.status.error.Please.exit.and.try.again");
            }
        }
        if (!Objects.equals(prod.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        Brand brand = brandService.getByBrandId(prod.getBrandId(), I18nMessage.getLang());
        if (Objects.nonNull(brand)) {
            prod.setBrand(brand);
        }
        List<ProdParameter> prodParameterList = prodParameterService.listParameterByProdId(prodId);
        prod.setProdParameterList(prodParameterList);
        prodExtensionService.getByProdId(prod.getProdId());
        List<Sku> skuList = skuService.listSkuAndSkuStock(prodId, I18nMessage.getLang());

        Set<Long> skuIds = getIsParticipate(prodId);
        for (Sku sku : skuList) {
            for (SkuLang skuLang : sku.getSkuLangList()) {
                // sku 规格国际化，因为不是关联表的形式，所以多语言一起返回数据
                if (Objects.equals(skuLang.getLang(), 1)) {
                    String propertiesEn = skuLang.getProperties();
                    String skuName = skuLang.getSkuName();
                    sku.setPropertiesEn(StrUtil.isNotBlank(propertiesEn) ? propertiesEn : sku.getProperties());
                    sku.setSkuNameEn(StrUtil.isNotBlank(skuName) ? skuName : sku.getSkuName());
                }
                // 适配一些数据
                if (StrUtil.isBlank(sku.getPropertiesEn())) {
                    sku.setPropertiesEn(sku.getProperties());
                }
            }
            sku.setIsParticipate(skuIds.contains(sku.getSkuId()) ? 1 : 0);
        }
        prod.setSkuList(skuList);
//        // 获取语言列表
//        List<ProdLang> prodLangList = prodLangService.list(new LambdaQueryWrapper<ProdLang>().eq(ProdLang::getProdId, prodId));
//        prod.setProdLangList(prodLangList);
        return ServerResponseEntity.success(prod);
    }

    @NotNull
    private Set<Long> getIsParticipate(Long prodId) {
        List<GiveawayProd> giveawayProds = giveawayProdService.list(new LambdaQueryWrapper<GiveawayProd>()
                .eq(GiveawayProd::getProdId, prodId)
                .eq(GiveawayProd::getStatus, 1));
        Set<Long> skuIds = giveawayProds.stream().map(GiveawayProd::getSkuId).collect(Collectors.toSet());
        List<ComboProdVO> comboProdList = comboProdService.listComboProdByProdId(prodId);
        for (ComboProdVO comboProd : comboProdList) {
            skuIds.addAll(comboProd.getSkuList().stream().map(ComboProdSkuVO::getSkuId).collect(Collectors.toSet()));
        }
        return skuIds;
    }

    @PostMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:save')")
    @ApiOperation(value = "新增商品", notes = "新增商品")
    public ServerResponseEntity<Long> save(@Valid @RequestBody ProductParam productParam) {
        checkParam(productParam);
        YamiShopUser shopUser = SecurityUtils.getShopUser();
        Long shopId = shopUser.getShopId();
        productParam.setProdName(productParam.getProdNameEn());
        productParam.setProdNameCn(productParam.getProdNameEn());
        productParam.setEmployeeId(shopUser.getEmployeeId());
        productParam.setEmployeeMobile(shopEmployeeService.getShopEmployeeById(productParam.getEmployeeId()).getMobile());
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
            // 店铺审核中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.AUDIT");
        }

        this.checkCategoryAndBrand(shopId, productParam.getCategoryId(), productParam.getShopCategoryId(), productParam.getBrandId());
        productParam.setShopId(shopId);
        if (Objects.nonNull(productParam.getProdType()) && Objects.equals(productParam.getProdType(), ProdType.PROD_TYPE_ACTIVE.value())) {
            productParam.setProdType(ProdType.PROD_TYPE_ACTIVE.value());
        } else {
            productParam.setProdType(ProdType.PROD_TYPE_NORMAL.value());
        }
        productService.saveProduct(productParam);
        eventPublisher.publishEvent(new EsProductUpdateEvent(productParam.getProdId(), null, EsOperationType.SAVE));
        return ServerResponseEntity.success(Objects.equals(productParam.getStatus(), ProdStatusEnums.NORMAL.getValue()) ? productParam.getProdId() : null);
    }

    @PutMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:update')")
    @ApiOperation(value = "修改商品", notes = "修改商品")
    public ServerResponseEntity<Long> update(@Valid @RequestBody ProductParam productParam) {
        checkParam(productParam);
        YamiShopUser shopUser = SecurityUtils.getShopUser();
        Product dbProduct = productService.getProductById(productParam.getProdId());
        productParam.setEmployeeId(shopUser.getEmployeeId());
        productParam.setEmployeeMobile(shopEmployeeService.getShopEmployeeById(productParam.getEmployeeId()).getMobile());
        if (Objects.equals(dbProduct.getStatus(), ProdStatusEnums.DELETE.getValue())) {
            // 产品已被删除
            throw new YamiShopBindException("yami.product.service.delete");
        }

        if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }

        if (!Objects.equals(dbProduct.getProdType(), productParam.getProdType())) {
            // 商品类型改变，请刷新页面后重试
            throw new YamiShopBindException("yami.prod.type.check");
        }

        if (!Objects.equals(dbProduct.getMold(), productParam.getMold())) {
            // 商品创建后不能修改商品类型
            throw new YamiShopBindException("yami.order.prod.type.check");
        }
        Long shopId = shopUser.getShopId();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }
        this.checkCategoryAndBrand(shopId, productParam.getCategoryId(), productParam.getShopCategoryId(), productParam.getBrandId());
        List<String> userIds = basketService.listUserIdByProdId(productParam.getProdId());


        List<Sku> dbSkus = skuService.listSkuAndSkuStock(dbProduct.getProdId(), I18nMessage.getDbLang());

        dbProduct.setSkuList(dbSkus);
        productParam.setProdType(productParam.getProdType());
        productService.updateProduct(productParam, dbProduct);

        //清除购物车缓存
        basketService.removeCacheByUserIds(userIds);
        productService.removeProdCacheByProdId(productParam.getProdId());
        prodParameterService.removeCacheByProdId(productParam.getProdId());
        for (Sku sku : dbSkus) {
            skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
        }
        applicationContext.publishEvent(new ComboEvent(dbProduct, productParam.getStatus()));
        eventPublisher.publishEvent(new EsProductUpdateEvent(productParam.getProdId(), null, EsOperationType.UPDATE));
        return ServerResponseEntity.success(Objects.equals(productParam.getStatus(), ProdStatusEnums.NORMAL.getValue()) ? productParam.getProdId() : null);
    }

    @DeleteMapping("/{prodId}")
    @PreAuthorize("@pms.hasPermission('prod:prod:delete')")
    @ApiOperation(value = "根据商品id删除商品", notes = "根据商品id删除商品")
    public ServerResponseEntity<Void> delete(@PathVariable("prodId") Long prodId) {
        Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        if (!Objects.equals(dbProduct.getShopId(), SecurityUtils.getShopUser().getShopId())) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        // 已经删除的商品
        if (Objects.equals(dbProduct.getStatus(), StatusEnum.DELETE.value())) {
            eventPublisher.publishEvent(new EsProductUpdateEvent(prodId, null, EsOperationType.DELETE));
            return ServerResponseEntity.success();
        }
        // 检查是否属于套餐或赠品
        this.checkBeforeDeleteProduct(prodId);
        List<Sku> dbSkus = skuService.listByProdId(dbProduct.getProdId(), I18nMessage.getDbLang());
        List<Long> supplierIds = supplierProdService.listSupplierIdByProdId(prodId);
        // 删除商品
        productService.removeProductByProdId(prodId);
        // 删除sku关联信息
        List<Long> deleteSkuIds = dbSkus.stream().map(Sku::getSkuId).collect(Collectors.toList());
        applicationContext.publishEvent(new SkuDeleteEvent(deleteSkuIds));
        if (CollectionUtils.isNotEmpty(supplierIds)) {
            for (Long supplierId : supplierIds) {
                supplierProdService.removeCacheBySupplierId(supplierId);
            }
        }
        productService.removeProdCacheByProdId(prodId);
        prodParameterService.removeCacheByProdId(prodId);
        if (Objects.nonNull(dbSkus)) {
            for (Sku sku : dbSkus) {
                skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
            }
        }

        List<String> userIds = basketService.listUserIdByProdId(prodId);
        // 商品状态改变时的发送事件，让活动下线
        applicationContext.publishEvent(new ProdChangeStatusEvent(dbProduct, ProdStatusEnums.DELETE.getValue()));
        applicationContext.publishEvent(new ComboEvent(dbProduct, ProdStatusEnums.DELETE.getValue()));
        if (Objects.nonNull(dbSkus)) {
            for (Sku sku : dbSkus) {
                skuService.removeSkuCacheBySkuId(sku.getSkuId(), sku.getProdId());
            }
        }
        //清除购物车缓存
        basketService.removeCacheByUserIds(userIds);
        eventPublisher.publishEvent(new EsProductUpdateEvent(prodId, null, EsOperationType.DELETE));
        return ServerResponseEntity.success();
    }

    @PutMapping("/prodStatus")
    @PreAuthorize("@pms.hasPermission('prod:prod:status')")
    @ApiOperation(value = "更新商品状态", notes = "更新商品状态")
    public ServerResponseEntity<Void> prodStatus(@RequestBody ProductParam productParam) {
        Long shopId = SecurityUtils.getShopUser().getShopId();
        Long prodId = productParam.getProdId();
        Integer prodStatus = productParam.getStatus();

        Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        checkProdInfo(productParam, shopId, dbProduct);

        Product product = new Product();
        product.setProdId(prodId);
        // 如果开启了商品审核，要上架商品默认进入待审核状态6
        SysProdConfig sysProdConfig = sysConfigService.getSysConfigObject(Constant.PROD_SWITCH_CONFIG, SysProdConfig.class);
        if (BooleanUtil.isTrue(sysProdConfig.getProdAudit()) && prodStatus == 1) {
            product.setStatus(ProdStatusEnums.AUDIT.getValue());
            dbProduct.setStatus(ProdStatusEnums.AUDIT.getValue());
        } else {
            product.setStatus(prodStatus);
            if (prodStatus == 1) {
                product.setPutawayTime(new Date());
            }
            dbProduct.setStatus(prodStatus);
        }
        product.setIsTop(0);

        // 商品状态改变时的发送事件，让活动下线
        applicationContext.publishEvent(new ProdChangeStatusEvent(dbProduct, dbProduct.getStatus()));
        applicationContext.publishEvent(new ComboEvent(dbProduct, productParam.getStatus()));

        productService.updateById(product);

        productService.removeProdCacheByProdId(prodId);
        List<String> userIds = basketService.listUserIdByProdId(prodId);
        //清除购物车缓存
        basketService.removeCacheByUserIds(userIds);
        eventPublisher.publishEvent(new EsProductUpdateEvent(product.getProdId(), null, EsOperationType.SAVE));
        return ServerResponseEntity.success();
    }

    private void checkProdInfo(ProductParam productParam, Long shopId, Product dbProduct) {
        if (!Objects.equals(dbProduct.getShopId(), shopId)) {
            // 查找不到该商品信息
            throw new YamiShopBindException("yami.product.not.exist");
        }
        if (!(Objects.equals(dbProduct.getStatus(), ProdStatusEnums.NORMAL.getValue())
                || Objects.equals(dbProduct.getStatus(), ProdStatusEnums.SHOP_OFFLINE.getValue()))) {
            // 商品不在正常状态，修改失败
            throw new YamiShopBindException("yami.product.on.normal");
        }
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(shopId);
        if (Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value()) || Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
            // 店铺处于违规下线中，不能修改商品，请联系管理员后重试
            throw new YamiShopBindException("yami.product.shop.offline");
        }


        if (Objects.equals(productParam.getStatus(), 1)) {
            Category category = categoryService.getById(dbProduct.getCategoryId());
            if (category == null || Objects.equals(category.getStatus(), 0)) {
                // 平台分类处于下线中，商品不能上架，请联系管理员后再进行操作
                throw new YamiShopBindException("yami.product.category.offline");
            }
            if(dbProduct.getWriteOffEnd()!=null && new Date().after(dbProduct.getWriteOffEnd())){
                //商品已过核销有效期
                throw new YamiShopBindException("该商品已过核销有效期");
            }
            Category shopCategory = categoryService.getById(dbProduct.getShopCategoryId());
            if (shopCategory == null || Objects.equals(shopCategory.getStatus(), 0)) {
                // 本店分类处于下线中，商品不能上架
                throw new YamiShopBindException("yami.product.shop.category.offline");
            }
            CategoryShop categoryShop = categoryShopService.getOne(Wrappers.lambdaQuery(CategoryShop.class).eq(CategoryShop::getShopId, shopId).eq(CategoryShop::getCategoryId, dbProduct.getCategoryId()));
            if (Objects.isNull(categoryShop)) {
                // 商品的分类签约失效
                throw new YamiShopBindException("yami.product.signing.category.invalid");
            }
        }
    }

    @DeleteMapping
    @PreAuthorize("@pms.hasPermission('prod:prod:batchDelete')")
    @ApiOperation(value = "根据商品id列表批量删除商品", notes = "根据商品id列表批量删除商品")
    public ServerResponseEntity<Boolean> batchRemoveById(@RequestBody Long[] ids) {
        // TODO 待优化
        StringBuilder stringBuilder = new StringBuilder();
        for (Long prodId : ids) {
            try {
                delete(prodId);
            } catch (Exception e) {
                Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
                stringBuilder.append("【").append(dbProduct.getProdName()).append("】  ");
            }
        }
        if (stringBuilder.length() > 0) {
            throw new YamiShopBindException("部分商品删除异常，请刷新页面后手动检查：" + stringBuilder.toString());
        }
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, Arrays.asList(ids), EsOperationType.DELETE_BATCH));
        return ServerResponseEntity.success();
    }

    @PutMapping("/batchProdStatus/{status}")
    @PreAuthorize("@pms.hasPermission('prod:prod:batchStatus')")
    @ApiOperation(value = "批量更新商品状态", notes = "批量更新商品状态")
    public ServerResponseEntity<Void> batchProdStatus(@RequestBody Long[] ids, @PathVariable("status") Integer status) {
        // TODO 待优化
        ProductParam product = new ProductParam();
        product.setStatus(status);
        StringBuilder stringBuilder = new StringBuilder();
        for (Long prodId : ids) {
            product.setProdId(prodId);
            try {
                prodStatus(product);
            } catch (Exception e) {
                Product dbProduct = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
                //【商品名】:错误信息xxx (【数码相机】:本店分类处于下线中，商品不能上架)
                stringBuilder.append("【" + dbProduct.getProdName() + "】:" + e.getMessage() + "\n");
            }
        }
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, Arrays.asList(ids), EsOperationType.UPDATE_BATCH));
        if (stringBuilder.length() > 0) {
            throw new YamiShopBindException("部分商品状态修改异常，请刷新页面后手动检查：" + stringBuilder.toString());
        }
        return ServerResponseEntity.success();
    }

    @PostMapping("/auditApply")
    @PreAuthorize("@pms.hasPermission('prod:prod:audit')")
    @ApiOperation(value = "违规商品提交审核", notes = "违规商品提交审核")
    public ServerResponseEntity<Void> auditApply(@RequestBody OfflineHandleEventAuditParam offlineHandleEventAuditParam) {
        Product product = productService.getProductByProdId(offlineHandleEventAuditParam.getHandleId(), I18nMessage.getDbLang());
        if (product == null) {
            // 商品信息不存在
            throw new YamiShopBindException("yami.product.no.exist");
        }
        productService.auditApply(offlineHandleEventAuditParam.getEventId(), offlineHandleEventAuditParam.getHandleId(), offlineHandleEventAuditParam.getReapplyReason());
        // 移除缓存
        productService.removeProdCacheByProdId(product.getProdId());
        eventPublisher.publishEvent(new EsProductUpdateEvent(product.getProdId(), null, EsOperationType.UPDATE));
        return ServerResponseEntity.success();
    }

    @GetMapping("/getOfflineHandleEventByProdId/{prodId}")
    @ApiOperation(value = "通过prodId获取最新下线商品的事件", notes = "通过prodId获取最新下线商品的事件")
    public ServerResponseEntity<OfflineHandleEvent> getByProdId(@PathVariable Long prodId) {
        OfflineHandleEvent offlineHandleEvent = offlineHandleEventService.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.PROD.getValue(), prodId);
        return ServerResponseEntity.success(offlineHandleEvent);
    }

    @GetMapping("/prodSkuPage")
    @ApiOperation(value = "分页获取商品及商品sku信息", notes = "分页获取商品及商品sku信息")
    public ServerResponseEntity<IPage<Product>> prodSkuPage(ProductParam product, PageParam<Product> page) {
        product.setLang(I18nMessage.getDbLang());
        product.setShopId(SecurityUtils.getShopUser().getShopId());
        IPage<Product> products = productService.prodSkuPage(page, product);
        return ServerResponseEntity.success(products);
    }

    @GetMapping(value = "/downloadModel")
    @PreAuthorize("@pms.hasPermission('prod:prod:downloadModel')")
    @ApiOperation(value = "下载商品导入模板", notes = "下载商品导入模板")
    public void downloadModel(HttpServletResponse response) {
        productExcelService.downloadModel(response, SecurityUtils.getShopUser().getShopId());
    }

    @RequestMapping(value = "/exportExcel", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "导入商品", notes = "导入商品")
    public ServerResponseEntity exportExcel(@RequestParam("excelFile") MultipartFile excelFile) throws Exception {
        if (excelFile == null) {
            // 网络繁忙，请稍后重试
            throw new YamiShopBindException("yami.network.busy");
        }
        Long shopId = SecurityUtils.getShopUser().getShopId();
        List<Long> prodIds = new ArrayList<>();
        Long employeeId = SecurityUtils.getShopUser().getEmployeeId();
        SameCity sameCity = sameCityService.getSameCityByShopId(shopId);
        // 是否开启同城配送
        boolean isSameCity = !Objects.isNull(sameCity) && Objects.equals(1, sameCity.getStatus());
        Object o = productExcelService.parseFile(excelFile, shopId, employeeId, prodIds, isSameCity);
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, prodIds, EsOperationType.SAVE_BATCH));
        return ServerResponseEntity.success(o);
    }

    private void checkParam(ProductParam productParam) {
        Long prodId = productParam.getProdId();
        Product.DeliveryModeVO deliveryMode = productParam.getDeliveryModeVo();
        boolean hasDeliverMode = deliveryMode != null
                && (deliveryMode.getHasShopDelivery() || deliveryMode.getHasUserPickUp() || deliveryMode.getHasCityDelivery());
        if (!hasDeliverMode) {
            // 请选择配送方式
            throw new YamiShopBindException("yami.product.dvy.type");
        }
        if (Objects.equals(productParam.getMold(), 1)) {
            // 虚拟商品的配送方式
            Product.DeliveryModeVO mode = new Product.DeliveryModeVO();
            mode.setHasShopDelivery(true);
            mode.setHasUserPickUp(false);
            mode.setHasCityDelivery(false);
            productParam.setDeliveryModeVo(mode);
        }
        //运费模板
        if(Objects.nonNull(productParam.getDeliveryTemplateId()) && !DeliveryTemplateType.isUnifiedTemplate(productParam.getDeliveryTemplateId())) {
            Transport transport = transportService.getTransportAndAllItems(productParam.getDeliveryTemplateId());
            if (Objects.isNull(transport)) {
                // 产品运费模板不存在
                throw new YamiShopBindException("yami.prod.transport.not.exist");
            }
        }

        // 统一运费-运费金额不能小于0
        if(Objects.equals(productParam.getDeliveryTemplateId(), DeliveryTemplateType.FREIGHT.getValue()) && productParam.getDeliveryAmount() < 0) {
            // 运费金额不能小于0
            throw new YamiShopBindException("yami.Shipping.amount.error");
        }
        Category category = categoryService.getById(productParam.getCategoryId());
        if (Objects.isNull(category)) {
            // 该平台分类已删除，请选择新的分类
            throw new YamiShopBindException("yami.prod.platform.category.deleted");
        }
        if (category.getGrade() < CategoryLevel.THIRD.value()) {
            // 请选择三级分类
            throw new YamiShopBindException("yami.prod.category.error");
        }
        //校验参与活动的sku不能修改价格
        Set<Long> skuIds = getIsParticipate(prodId);
        List<Sku> skus = new ArrayList<>();
        if (CollUtil.isNotEmpty(skuIds)) {
            skus = skuService.listByProdId(prodId, I18nMessage.getDbLang());
        }
        Map<Long, Double> skuMap = skus.stream().collect(Collectors.toMap(Sku::getSkuId, Sku::getPrice));
        List<Sku> skuList = productParam.getSkuList();
        Long shopId = SecurityUtils.getShopUser().getShopId();
        //商品编码
        List<Product> products = productService.list(new LambdaQueryWrapper<Product>().eq(Product::getShopId, shopId)
                .eq(Product::getStatus, 1));
        List<Long> prodIds = products.stream().map(Product::getProdId).collect(Collectors.toList());
        List<String> partyCodes = skuService.listSkuByProdIds(prodIds, prodId);
        boolean isAllUnUse = true;
        for (Sku sku : skuList) {
            Long skuId = sku.getSkuId();
            if (skuIds.contains(skuId) && !Objects.equals(skuMap.get(skuId),sku.getPrice())) {
                //参加了套餐或赠品活动，无法更改价格，请刷新页面重试
                String skuError = I18nMessage.getMessage("yami.sku.price.not.change");
                throw new YamiShopBindException("sku" + sku.getSkuName() + skuError);
            }
            //雪花算法生成商品编码
            if (StrUtil.isBlank(sku.getPartyCode())) {
                String partyCode = StringUtils.join("RM", String.valueOf(snowflake.nextId()));
                sku.setPartyCode(partyCode);
            }
            if (CollectionUtils.isNotEmpty(partyCodes) && partyCodes.contains(sku.getPartyCode())) {
                String message = I18nMessage.getMessage("yami.sku.party.code");
                String isExit = I18nMessage.getMessage("yami.is.exist");
                //商品编码已存在
                throw new YamiShopBindException(message + sku.getPartyCode() + isExit);
            }
            if (sku.getStatus() == 1) {
                isAllUnUse = false;
            }
        }
        if (isAllUnUse) {
            // 至少要启用一种商品规格
            throw new YamiShopBindException("yami.product.enable.sku");
        }
    }

    /**
     * 检查分类与品牌是否可用
     *
     * @param shopId         店铺id
     * @param categoryId     平台分类
     * @param shopCategoryId 店铺分类
     * @param brandId        品牌id
     */
    private void checkCategoryAndBrand(Long shopId, Long categoryId, Long shopCategoryId, Long brandId) {
        Category category = categoryService.getOne(Wrappers.lambdaQuery(Category.class).eq(Category::getCategoryId, categoryId));
        if (Objects.isNull(category) || !Objects.equals(category.getStatus(), StatusEnum.ENABLE.value())) {
            throw new YamiShopBindException("yami.product.category.not.under");
        }

        CategoryShop categoryShop = categoryShopService.getOne(Wrappers.lambdaQuery(CategoryShop.class).eq(CategoryShop::getShopId, shopId).eq(CategoryShop::getCategoryId, categoryId));
        if (Objects.isNull(categoryShop) || !Objects.equals(categoryShop.getStatus(), SigningStatus.SUCCESS.value())) {
            throw new YamiShopBindException("yami.product.category.not.under");
        }

        Category shopCategory = categoryService.getOne(Wrappers.lambdaQuery(Category.class).eq(Category::getShopId, shopId).eq(Category::getCategoryId, shopCategoryId));
        if (Objects.isNull(shopCategory) || !Objects.equals(shopCategory.getStatus(), SigningStatus.SUCCESS.value())) {
            // 当前店铺分类已不可用，请刷新分类列表重新选择
            throw new YamiShopBindException("yami.product.shop.category.not.under");
        }
        if (Objects.isNull(brandId) || Objects.equals(brandId, 0L)) {
            return;
        }
        Brand brand = brandService.getOne(Wrappers.lambdaQuery(Brand.class).eq(Brand::getBrandId, brandId));
        if (Objects.isNull(brand) || !Objects.equals(brand.getStatus(), StatusEnum.ENABLE.value())) {
            throw new YamiShopBindException("yami.product.brand.not.under");
        }
        BrandShop brandShop = brandShopService.getOne(Wrappers.lambdaQuery(BrandShop.class).eq(BrandShop::getShopId, shopId).eq(BrandShop::getBrandId, brandId));
        int categoryBrandCount = categoryBrandService.count(Wrappers.lambdaQuery(CategoryBrand.class).eq(CategoryBrand::getCategoryId, categoryId).eq(CategoryBrand::getBrandId, brandId));
        if (Objects.isNull(brandShop)) {
            if (categoryBrandCount <= 0) {
                throw new YamiShopBindException("yami.product.brand.not.under");
            }
        } else {
            if (!Objects.equals(brandShop.getStatus(), SigningStatus.SUCCESS.value())) {
                throw new YamiShopBindException("yami.product.brand.not.under");
            }
        }
    }

    private void checkBeforeDeleteProduct(Long prodId) {
        GetComboProdCountEvent getComboProdCountEvent = new GetComboProdCountEvent();
        getComboProdCountEvent.setProdId(prodId);
        applicationContext.publishEvent(getComboProdCountEvent);
        if (getComboProdCountEvent.getCount() > 0) {
            //参加以下活动的商品不能被删除：优惠套餐
            throw new YamiShopBindException("yami.combo.prod.not.delete");
        }
        GetGiveawayProdCountEvent getGiveawayProdCountEvent = new GetGiveawayProdCountEvent();
        getGiveawayProdCountEvent.setProdId(prodId);
        applicationContext.publishEvent(getGiveawayProdCountEvent);
        if (getGiveawayProdCountEvent.getCount() > 0) {
            //参加以下活动的商品不能被删除：赠品
            throw new YamiShopBindException("yami.giveaway.prod.not.delete");
        }
    }
}
